/* CsJni - .NET / Java Bridge
 * 
 * Copyright 2010 Robert E. Burke Licensed under the Apache License, Version 
 * 2.0 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at 
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 
 * law or agreed to in writing, software distributed under the License is 
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 * KIND, either express or implied. See the License for the specific language 
 * governing permissions and limitations under the License. 
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace CsJni
{
    public sealed partial class JavaVM
    {
        private class JniInvokeInterface
        {
            // Not using the following methods:
            // AttachCurrentThreadAsDaemon

            #region Delegate Declarations

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int DestroyJavaVM_Handler(
                /* JavaVM* */ IntPtr vm
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate /* jint */ int AttachCurrentThread_Handler(
                /* JavaVM* */ IntPtr vm,
                void*** pppenv,
                void* args
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public delegate /* jint */ int DetachCurrentThread_Handler(
                /* JavaVM* */ IntPtr vm
                );

            [UnmanagedFunctionPointer(JavaVM.CC)]
            public unsafe delegate /* jint */ int GetEnv_Handler(
                /* JavaVM* */ IntPtr vm,
                void*** pppenv,
                /* jint */ int version
                );


            // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
            // corresponding delegates will be null

            #endregion Delegate Declarations 

            #region Delegate Fields

            public DestroyJavaVM_Handler DestroyJavaVM;
            public AttachCurrentThread_Handler AttachCurrentThread;
            public DetachCurrentThread_Handler DetachCurrentThread;
            public GetEnv_Handler GetEnv;

            // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
            // corresponding delegates will be null

            #endregion Delegate Fields 

            public JniInvokeInterface(IntPtr javaVMHandle, JniVersion jniVersion)
            {
                IntPtr functionTableBaseAddress = Marshal.ReadIntPtr(javaVMHandle);
                int countFunctionPointers = 8; // for JniVersion.Version1Minor4
                if (jniVersion == JniVersion.Version1Minor2)
                {
                    countFunctionPointers = 7;
                }
                IntPtr[] functionTable = new IntPtr[countFunctionPointers];
                Marshal.Copy(functionTableBaseAddress, functionTable, 0, functionTable.Length);
                Init(functionTable, jniVersion);
            }

            private static T GetDel<T>(IntPtr functionPointer)
            {
                return (T)(object)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(T));
            }

            private unsafe void Init(IntPtr[] functionTable, JniVersion jniVersion)
            {
                #region Delegate Initialization

                this.DestroyJavaVM = GetDel<DestroyJavaVM_Handler>(functionTable[3]);
                this.AttachCurrentThread = GetDel<AttachCurrentThread_Handler>(functionTable[4]);
                this.DetachCurrentThread = GetDel<DetachCurrentThread_Handler>(functionTable[5]);
                this.GetEnv = GetDel<GetEnv_Handler>(functionTable[6]);

                // The remainder of JNI Methods are for JNI_VERSION_1_4 or higher, 
                // corresponding delegates will be null

                if (jniVersion == JniVersion.Version1Minor2)
                {
                    return;
                }

                #endregion Delegate Initialization
            }
        }
    }
}
